home *** CD-ROM | disk | FTP | other *** search
- /*
- * ACKNOWLEDGEMENTS
- *
- * ZMDM was derived from rz/sz for Unix posted by
- * Chuck Forsberg (...!tektronix!reed!omen!caf ). We
- * thank him for his excellent code, and for giving
- * us permission to use and distribute his code and
- * documentation.
- *
- * Atari St version by:
- * Jwahar Bammi
- * usenet: cwruecmp!bammi@decvax.UUCP
- * csnet: bammi@cwru.edu
- * arpa: bammi@cwru.edu
- * CompuServe: 71515,155
- */
-
- #define SVERSION "sz 1.23 01-15-87"
- #define SSTVERSION "sz 1.01 03-07-87"
- #define OS "Unix V7/BSD"
-
- /* #define SDEBUG */
-
- /*% cc -O -K -DCRCTABLE -DREADCHECK sz.c -lx -o sz; size sz
-
- * sz.c By Chuck Forsberg
- *
- * cc -O sz.c -o sz USG (SYS III/V) Unix
- * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD
- *
- * define CRCTABLE to use table driven CRC
- *
- * ******* Some systems (Venix, Coherent, Regulus) do not *******
- * ******* support tty raw mode read(2) identically to *******
- * ******* Unix. ONEREAD must be defined to force one *******
- * ******* character reads for these systems. *******
- *
- * A program for Unix to send files and commands to computers running
- * Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
- *
- * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
- *
- * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
- *
- * St v 1.01
- * added support for 32 bit CRC's (Zmodem) ++jrb
- *
- */
-
- #include "zmdm.h"
- #include "common.h"
- #include "zmodem.h"
-
- #define SLOGFILE "szlog"
-
- #define purgeline() while(Bconstat(1)) Bconin(1)
- #define S_IFDIR 0x0010
-
- /*
- * Attention string to be executed by receiver to interrupt streaming data
- * when an error is detected. A pause (0336) may be needed before the
- * ^C (03) or after it.
- */
- #ifdef READCHECK
- char Myattn[] = { 0 };
- #else
- #ifdef USG
- char Myattn[] = { 03, 0336, 0 };
- #else
- char Myattn[] = { 0 };
- #endif
- #endif
-
- #ifdef MWC
- FILE *fopen();
- #else
- FILE *fopen(), *fopenb();
- #endif
- static unsigned long SaveIntr;
- static int Resuming;
- static int in;
-
- /* called by signal interrupt or terminate to clean things up */
- bibis(n)
- int n;
- {
- canit(); flush_modem(); mode(0);
- fprintf(stderr, "\r\nsz: caught signal %d; exiting\n", n);
-
- aexit(128+n);
- }
-
- /* Called when Zmodem gets an interrupt (^X) */
- #ifdef ONINTR
- onintr()
- {
- siggi = 0;
- longjmp(intrjmp, -1);
- }
- #endif
-
- #define ZKER
- int Zctlesc; /* Encode control characters */
-
-
- int dosz(argc, argv)
- int argc;
- char **argv;
- {
- register char *cp;
- register int npats;
- int agcnt; char **agcv;
- char **patts;
-
-
- SendType = 1;
- Rxtimeout = 600;
- npats=0;
- if (argc<2)
- {
- susage();
- return(1);
- }
-
- initz();
- schkinvok(argv[0]);
- SaveIntr = Setexc(0x0102, -1L);
- BusErr = Setexc(2, -1L);
- AddrErr = Setexc(3, -1L);
-
- Verbose = 0;
- Resuming = FALSE;
- in = (-1);
- vdebug = 0;
-
- #ifdef SDEBUG
- logf = (FILE *)NULL;
- #endif
- while (--argc) {
- cp = *++argv;
- if (*cp++ == '-' && *cp) {
- while ( *cp) {
- switch(*cp++) {
- case '+':
- Lzmanag = ZMAPND; break;
- #ifdef CSTOPB
- case '2':
- Twostop = TRUE; break;
- #endif
- case '7':
- Wcsmask=0177; break;
-
- /*
- On the St we look up the ext and decide. For Xmodem
- transfers, the file is always sent in binary mode
- and it is the responsibility of the receiver to
- strip CR if so desired.
- case 'a':
- Lzconv = ZCNL;
- Ascii = TRUE; break;
- case 'b':
- Lzconv = ZCBIN; break;
- */
- case 'C':
- if (--argc < 1) {
- susage();
- return(1);
- }
- Cmdtries = atoi(*++argv);
- break;
- case 'i':
- Cmdack1 = ZCACK1;
- /* **** FALL THROUGH TO **** */
- case 'c':
- if (--argc != 1) {
- susage();
- return(1);
- }
- Command = TRUE;
- Cmdstr = *++argv;
- break;
- case 'd':
- ++Dottoslash;
- /* **** FALL THROUGH TO **** */
- case 'f':
- Fullname=TRUE; break;
- case 'E':
- Zctlesc = (-1); break;
- case 'e':
- Zctlesc = 1; break;
- case 'k':
- Blklen=KSIZE; break;
- case 'L':
- if (--argc < 1) {
- susage();
- return(1);
- }
- blkopt = atoi(*++argv);
- if (blkopt<32 || blkopt>1024)
- {
- susage();
- return(1);
- }
- break;
- case 'l':
- if (--argc < 1) {
- susage();
- return(1);
- }
- Tframlen = atoi(*++argv);
- if (Tframlen<32 || Tframlen>1024)
- {
- susage();
- return(1);
- }
- break;
- case 'N':
- Lzmanag = ZMDIFF; break;
- case 'n':
- Lzmanag = ZMNEW; break;
- case 'o':
- Wantfcs32 = FALSE; break;
- case 'p':
- Lzmanag = ZMPROT; break;
- case 'r':
- Lzconv = ZCRESUM; Resuming = TRUE; break;
- case 'q':
- Quiet=TRUE; Verbose=0; break;
- case 't':
- if (--argc < 1) {
- susage();
- return(1);
- }
- Rxtimeout = atoi(*++argv);
- if (Rxtimeout<10 || Rxtimeout>1000)
- {
- susage();
- return(1);
- }
- break;
- #ifdef TESTATTN
- case 'T':
- Testattn = TRUE; break;
- #endif
- case 'u':
- ++Unlinkafter; break;
- case 'v':
- ++Verbose; break;
- case 'X':
- ++Modem; break;
- case 'y':
- Lzmanag = ZMCLOB; break;
- default:
- susage();
- return(1);
- }
- }
- }
- else if ( !npats && argc>0) {
- if (argv[0][0]) {
- npats=argc;
- patts=argv;
- }
- }
- }
- if (npats < 1 && !Command)
- {
- susage();
- return(1);
- }
-
- #ifdef SDEBUG
- if (Verbose > 2)
- {
- if ((logf = fopen(SLOGFILE, "a"))== (FILE *)NULL)
- {
- fprintf(stderr, "Can't open log file %s\n",SLOGFILE);
- return(0200);
- }
- fprintf(logf, "Progname=%s\n", Progname);
- vdebug = 1;
- fflush(logf);
- }
- #endif
-
- if ( !Quiet)
- {
- if (Verbose < 2)
- Verbose = 2;
- }
-
-
- Setexc(0x0102, bibis);
- Setexc(2, buserr);
- Setexc(3, addrerr);
-
- if(setjmp(busjmp))
- {
- /* On a bus error - instead of 2 bombs */
- fprintf(stderr,"\r\nFATAL: Bus Error\n\n");
- #ifdef SDEBUG
- if(logf != (FILE *)NULL)
- fclose(logf);
- #endif
- if(in != -1)
- {
- stfclose(in);
- in = (-1);
- }
- canit();
- Setexc(2, BusErr);
- Setexc(3, AddrErr);
- Setexc(0x0102, SaveIntr);
- return(2);
- }
-
- if(setjmp(addrjmp))
- {
- /* On address error - instead of 3 bombs */
- fprintf(stderr,"\r\nFATAL: Address Error\n\n");
- #ifdef SDEBUG
- if(logf != (FILE *)NULL)
- fclose(logf);
- #endif
- if(in != -1)
- {
- stfclose(in);
- in = (-1);
- }
- canit();
- Setexc(2, BusErr);
- Setexc(3, AddrErr);
- Setexc(0x0102, SaveIntr);
- return(3);
- }
-
- if((Exitcode = setjmp(abrtjmp)))
- {
- fprintf(stderr,"\nTransfer ABORT\n\n");
- #ifdef SDEBUG
- if(logf != (FILE *)NULL)
- fclose(logf);
- #endif
- if(in != -1)
- {
- stfclose(in);
- in = (-1);
- }
- Setexc(2, BusErr);
- Setexc(3, AddrErr);
- Setexc(0x0102, SaveIntr);
- return(Exitcode);
- }
-
- mode(1);
-
-
- if ( !Modem) {
- if (!Command && !Quiet && Verbose != 1)
- {
- fprintf(stderr, "sz: %d file%s requested:\n",
- npats, npats>1?"s":"");
- for ( agcnt=npats, agcv=patts; --agcnt>=0; )
- {
- fprintf(stderr, "%s ", *agcv++);
- }
- fprintf(stderr, "\n\n");
-
- #ifdef SDEBUG
- if(Verbose > 2)
- {
- fprintf(logf, "sz: %d file%s requested:\n",
- npats, npats>1?"s":"");
- for ( agcnt=npats, agcv=patts; --agcnt>=0; )
- {
- fprintf(logf, "%s ", *agcv++);
- }
- fprintf(logf, "\n");
- fflush(logf);
- }
- #endif
- }
- if (!Nozmodem) {
- stohdr(0L);
- if (Command)
- Txhdr[ZF0] = ZCOMMAND;
- zshhdr(ZRQINIT, Txhdr);
- }
- }
- flush_modem();
-
- if (Command) {
- if (getzrxinit()) {
- Exitcode=0200; canit();
- }
- else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
- Exitcode=0200; canit();
- }
- } else if (wcsend(npats, patts)==ERROR) {
- Exitcode=0200;
- canit();
- }
- flush_modem();
- mode(0);
-
- #ifdef SDEBUG
- if(logf != (FILE *)NULL)
- fclose(logf);
- #endif
- if(in != -1)
- {
- fclose(in);
- in = (-1);
- }
-
- putc('\n', stderr);
- Setexc(2, BusErr);
- Setexc(3, AddrErr);
- Setexc(0x0102, SaveIntr);
- return((errcnt != 0) | Exitcode);
- /*NOTREACHED*/
- }
-
- wcsend(argc, argp)
- char *argp[];
- {
- register int n;
-
- Crcflg=FALSE;
- Firstsec=TRUE;
- for (n=0; n<argc; ++n) {
- Totsecs = 0;
- if (wcs(argp[n])==ERROR)
- return ERROR;
- }
- Totsecs = 0;
- if (Filcnt==0) { /* bitch if we couldn't open ANY files */
- if (1) {
- Command = TRUE;
- Cmdstr = "echo \"sz: Can't open any requested files\"";
- if (getzrxinit()) {
- Exitcode=0200; canit();
- }
- else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
- Exitcode=0200; canit();
- }
- Exitcode = 1; return OK;
- }
- canit();
- fprintf(stderr,"\n\nCan't open any requested files.\n\n");
- return ERROR;
- }
- if (Zmodem)
- saybibi();
- else
- wctxpn("");
- return OK;
- }
-
- wcs(oname)
- char *oname;
- {
- extern struct stat statbuf;
- char name[PATHLEN];
-
- strcpy(name, oname);
- ++Noeofseen; Lastread = 0; Lastc = (-1); Dontread = FALSE;
-
- /* Check for directory or block special files */
- if(Fsfirst(name,(int)(0x01 | 0x010 | 0x020)) != 0)
- {
- ++errcnt;
- return OK; /* may be others */
- }
-
- if (statbuf.st_mode & S_IFDIR ) {
- return OK;
- }
-
- if((in = stfopen(oname,"r")) <= 0){
- ++errcnt;
- return OK; /* pass over it, there may be others */
- }
-
- ++Filcnt;
- switch (wctxpn(name)) {
- case ERROR:
- return ERROR;
- case ZSKIP:
- return OK;
- }
- if (!Zmodem && wctx()==ERROR)
- return ERROR;
- if (Unlinkafter)
- unlink(oname);
- return 0;
- }
-
- #define ISDRIVE(X) ( (((X >= 'a') && (X <= 'n'))) || ((X >= 'A') && (X <= 'N')))
- /*
- * generate and transmit pathname block consisting of
- * pathname (null terminated),
- * file length, mode time and file mode in octal
- * as provided by the St's Fsfirst() call.
- * N.B.: modifies the passed name, may extend it!
- */
- wctxpn(name)
- char *name;
- {
- register char *p, *q;
- char name2[PATHLEN];
- unsigned long unixtime;
- extern struct stat statbuf;
- extern unsigned long st2unix(); /* Convert St's date and time to unix
- time (seconds since Jan 1 1970 00:00:00) */
-
- if(*name)
- if(Fsfirst(name,(int)(0x01 | 0x020)) != 0)
- return ERROR;
-
- if (Modem) {
- if (*name) {
- fprintf(stderr, "Outgoing:\n\t Name: %s\n\t Size: %ld Bytes\n\tBlocks: %ld\n\n",
- name, statbuf.st_size, statbuf.st_size>>7);
- }
- return OK;
- }
-
- vfile2("\r\nAwaiting pathname nak for %s\r\n", *name?name:"<END>");
-
- if ( !Zmodem)
- if (getnak())
- return ERROR;
-
- /* convert to Unix style path names */
- /* skip any device identifier */
- if(ISDRIVE(name[0]) && (name[1] == ':'))
- name = &name[2];
-
- for(p = name; *p != '\0'; p++)
- {
- if(*p == '\\')
- *p = '/';
- }
-
- if(!Resuming)
- {
- if(!isbinary(name))
- {
- /* We indicate to the other side */
- Lzconv = ZCNL;
- Ascii = TRUE;
- }
- else
- {
- Lzconv = ZCBIN;
- Ascii = FALSE;
- }
- }
-
- q = (char *) 0;
- if (Dottoslash) { /* change . to . */
- for (p=name; *p; ++p) {
- if (*p == '/')
- q = p;
- else if (*p == '.')
- *(q=p) = '/';
- }
- if (q && strlen(++q) > 8) { /* If name>8 chars */
- q += 8; /* make it .ext */
- strcpy(name2, q); /* save excess of name */
- *q = '.';
- strcpy(++q, name2); /* add it back */
- }
- }
-
- for (p=name, q=secbuf ; *p; )
- if ((*q++ = *p++) == '/' && !Fullname)
- q = secbuf;
- *q++ = 0;
- p=q;
- while (q < (secbuf + KSIZE))
- *q++ = 0;
- if (*name)
- {
- unixtime = st2unix(statbuf.st_time, statbuf.st_date);
- sprintf(p, "%lu %lo %o", statbuf.st_size,
- unixtime,
- ((statbuf.st_mode & 0x01)?0444:0644));
- }
-
- if(Verbose)
- fprintf(stderr,
- "Outgoing: [Hit CTRL-C to Cancel]\n\tName: %s\n\tSize: %ld Bytes\n",
- name, statbuf.st_size);
- if(!Resuming)
- {
- fprintf(stderr,"\tMode: %s\n\n", (Ascii)?"ASCII":"BINARY");
- }
- else
- {
- fprintf(stderr,"\tMode: Resume Transfer Mode\n\n");
- }
-
- #ifdef SDEBUG
- if(Verbose > 2)
- {
- fprintf(stderr,"File: %s (%s)\n", name, p);
- fprintf(logf,"File: %s (%s)\n", name, p);
- fflush(logf);
- }
- #endif
-
- /* force 1k blocks if name won't fit in 128 byte block */
- if (secbuf[125])
- Blklen=KSIZE;
- else { /* A little goodie for IMP/KMD */
- if (Zmodem)
- Blklen = SECSIZ;
- secbuf[127] = (statbuf.st_size + 127) >>7;
- secbuf[126] = (statbuf.st_size + 127) >>15;
- }
- if (Zmodem)
- return zsendfile(secbuf, (int)(1+strlen(p)+
- (int)((long)p-(long)secbuf)));
- if (wcputsec(secbuf, 0, SECSIZ)==ERROR)
- return ERROR;
- return OK;
- }
-
- getnak()
- {
- register int firstch;
-
- Lastrx = 0;
- for (;;) {
- switch (firstch = readock(800,1)) {
- case ZPAD:
- if (getzrxinit())
- return ERROR;
- Ascii = 0;
- return FALSE;
- case TIMEOUT:
- vfile("Timeout on pathname\n");
- return TRUE;
- case WANTG:
- #ifdef USG
- mode(2); /* Set cbreak, XON/XOFF, etc. */
- #endif
- Optiong = TRUE;
- Blklen=KSIZE;
- case WANTCRC:
- Crcflg = TRUE;
- case NAK:
- return FALSE;
- case CAN:
- if ((firstch = readock(20,1)) == CAN && Lastrx == CAN)
- return TRUE;
- default:
- break;
- }
- Lastrx = firstch;
- }
- }
-
-
- wctx()
- {
- register int sectnum, attempts, firstch;
-
- Firstsec=TRUE;
-
- while ((firstch=readock(Rxtimeout, 2))!=NAK && firstch != WANTCRC
- && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
- ;
- if (firstch==CAN) {
- fprintf(stderr, "\r\nReceiver CANcelled\n");
- return ERROR;
- }
- if (firstch==WANTCRC)
- Crcflg=TRUE;
- if (firstch==WANTG)
- Crcflg=TRUE;
- sectnum=1;
- while (filbuf(secbuf, Blklen)) {
- if (wcputsec(secbuf, sectnum, Blklen)==ERROR) {
- return ERROR;
- } else
- sectnum++;
- }
-
- if (Verbose>1)
- {
- fprintf(stderr, "\nClosing\n\n");
- #ifdef SDEBUG
- if(Verbose > 2)
- {
- fprintf(logf, " Closing\n");
- fflush(logf);
- }
- #endif
- }
-
- stfclose(in);
- in = (-1);
-
- attempts=0;
- do {
- vfile(" EOT ");
- purgeline();
- sendline(EOT);
- flush_modem();
- ++attempts;
- }
- while ((firstch=(readock(Rxtimeout, 1)) != ACK) && attempts < RETRYMAX);
- if (attempts == RETRYMAX) {
- fprintf(stderr, "\r\nNo ACK on EOT\n");
- return ERROR;
- }
- else
- return OK;
- }
-
- wcputsec(buf, sectnum, cseclen)
- char *buf;
- int sectnum;
- int cseclen; /* data length of this sector to send */
- {
- register int checksum, wcj;
- register char *cp;
- unsigned int oldcrc;
- int firstch;
- int attempts;
-
- firstch=0; /* part of logic to detect CAN CAN */
-
- if (Verbose>1)
- {
- fprintf(stderr, "\rBlock %06d %04dK ", Totsecs, (Totsecs>>3));
- #ifdef SDEBUG
- if(Verbose > 2)
- {
- fprintf(logf, "\rBlock %d %dK ", Totsecs, (Totsecs>>3) );
- fflush(logf);
- }
- #endif
- }
-
- for (attempts=0; attempts <= RETRYMAX; attempts++) {
- Lastrx= firstch;
- sendline(cseclen==KSIZE?STX:SOH);
- sendline(sectnum);
- sendline(-sectnum -1);
- oldcrc=checksum=0;
- for (wcj=cseclen,cp=buf; --wcj>=0; ) {
- sendline(*cp);
- oldcrc=updcrc((0377& *cp), oldcrc);
- checksum += *cp++;
- }
- if (Crcflg) {
- oldcrc=updcrc(0,updcrc(0,oldcrc));
- sendline((int)oldcrc>>8);
- sendline((int)oldcrc);
- }
- else
- sendline(checksum);
-
- if (Optiong) {
- Firstsec = FALSE; return OK;
- }
- firstch = readock(Rxtimeout, (Noeofseen&§num) ? 2:1);
- gotnak:
- switch (firstch) {
- case CAN:
- if(Lastrx == CAN) {
- cancan:
- fprintf(stderr, "\r\nCancelled\n"); return ERROR;
- }
- break;
- case TIMEOUT:
- vfile("Timeout on sector ACK\n"); continue;
- case WANTCRC:
- if (Firstsec)
- Crcflg = TRUE;
- case NAK:
- vfile("NAK on sector\n"); continue;
- case ACK:
- Firstsec=FALSE;
- Totsecs += (cseclen>>7);
- return OK;
- case ERROR:
- vfile("Got burst for sector ACK\n"); break;
- default:
- vfile("Got %02x for sector ACK\n", firstch); break;
- }
- for (;;) {
- Lastrx = firstch;
- if ((firstch = readock(Rxtimeout, 2)) == TIMEOUT)
- break;
- if (firstch == NAK || firstch == WANTCRC)
- goto gotnak;
- if (firstch == CAN && Lastrx == CAN)
- goto cancan;
- }
- }
- fprintf(stderr, "\r\nRetry Count Exceeded\n");
- return ERROR;
- }
-
- /* fill buf with count chars padding with ^Z for CPM */
- filbuf(buf, count)
- register unsigned char *buf;
- register int count;
- {
- register int m;
-
- if((buf[0] = stgetc(in)) == EOF)
- return 0;
-
- for(m = 1; (m < count) && ((buf[m] = stgetc(in)) != EOF); m++)
- /* loop */ ;
-
- while (m < count)
- buf[m++] = 032;
-
- return count;
-
- }
- /* fill buf with count chars */
- zfilbuf(buf, count)
- register char *buf;
- {
- register int c, m;
-
- m=count;
- while ((c=stgetc(in))!=EOF) {
- *buf++ =c;
- if (--m == 0)
- break;
- }
- return (count - m);
- }
-
- /*
- * readock(timeout, count) reads character(s) from file descriptor 0
- * (1 <= count <= 3)
- * it attempts to read count characters. If it gets more than one,
- * it is an error unless all are CAN
- * (otherwise, only normal response is ACK, CAN, or C)
- * Only looks for one if Optiong, which signifies cbreak, not raw input
- *
- * timeout is in tenths of seconds
- */
- readock(timeout, count)
- int timeout, count;
- {
- register int c;
- static char byt[5];
-
- if (Optiong)
- count = 1; /* Special hack for cbreak */
-
- if (setjmp(tohere)) {
- vfile("TIMEOUT\n");
- return TIMEOUT;
- }
- c = timeout >> 3;
- if (c<2)
- c=2;
- #ifdef SDEBUG
- if (Verbose>3) {
- fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c);
- byt[1] = 0;
- fprintf(logf, "Timeout=%d Calling alarm(%d) ", timeout, c);
- fflush(logf);
-
- }
- #endif
- stalarm(c);
- c=read_modem(byt, count);
-
- stalarm(0);
- #ifdef SDEBUG
- if (Verbose>5)
- {
- fprintf(stderr, "ret cnt=%d %x %x\n", c, byt[0], byt[1]);
- fprintf(logf, "ret cnt=%d %x %x\n", c, byt[0], byt[1]);
- fflush(logf);
- }
- #endif
-
- if (c<1)
- return TIMEOUT;
- if (c==1)
- return (byt[0]&0377);
- else
- while (c)
- if (byt[--c] != CAN)
- return ERROR;
- return CAN;
- }
-
- sreadline(n)
- {
- return (readock(n, 1));
- }
-
-
- susage()
- {
- fprintf(stderr,"\nSend file(s) with ZMODEM/YMODEM/XMODEM Protocol\n");
- fprintf(stderr," (Y) = Option applies to YMODEM only\n");
- fprintf(stderr," (Z) = Option applies to ZMODEM only\n");
- fprintf(stderr,
- "%s for %s by ST Enthusiasts at Case Western Reserve University\n",
- SSTVERSION, STOS);
- fprintf(stderr,"\tBased on %s for %s by Chuck Forsberg\n\n", SVERSION, OS);
- /* fprintf(stderr,"Usage: sz [-12+adefknquvXy] [-] file ...\n"); */
- fprintf(stderr,"Usage: sz [-+defknquvXy] file ...\n");
- /* fprintf(stderr," sz [-1eqv] -c COMMAND\n"); */
- fprintf(stderr," sz [-eqv] -c COMMAND\n");
- /* fprintf(stderr," 1 Use stdout for modem input\n"); */
- #ifdef CSTOPB
- fprintf(stderr," 2 Use 2 stop bits\n");
- #endif
- fprintf(stderr," + Append to existing destination file (Z)\n");
- /* fprintf(stderr," a (ASCII) change NL to CR/LF\n"); */
- fprintf(stderr," c send COMMAND (Z)\n");
- fprintf(stderr," d Change '.' to '/' in pathnames (Y/Z)\n");
- fprintf(stderr," e Escape control characters (Z)\n");
- fprintf(stderr," f send Full pathname (Y/Z)\n");
- fprintf(stderr," i send COMMAND, ack Immediately (Z)\n");
- fprintf(stderr," k Send 1024 byte packets (Y)\n");
- fprintf(stderr," L N Limit packet length to N bytes (Z)\n");
- fprintf(stderr," l N Limit frame length to N bytes (l>=L) (Z)\n");
- fprintf(stderr," n send file if Newer|longer (Z)\n");
- fprintf(stderr," N send file if different length|date (Z)\n");
- fprintf(stderr, " o Use 16 bit CRC instead of 32 bit CRC (Z)\n");
- fprintf(stderr," p Protect existing destination file (Z)\n");
- fprintf(stderr," r Resume/Recover interrupted file transfer (Z)\n");
- fprintf(stderr," q Quiet (no progress reports)\n");
- fprintf(stderr," u Unlink file after transmission\n");
- fprintf(stderr," v Verbose - debugging information\n");
- fprintf(stderr," X XMODEM protocol - send no pathnames\n");
- fprintf(stderr," y Yes, overwrite existing file (Z)\n");
- /* fprintf(stderr,
- "- as pathname sends standard input as sPID.sz or environment ONAME\n"); */
- return(1);
- }
-
- /*
- * Get the receiver's init parameters
- */
- getzrxinit()
- {
- register int n;
-
- for (n=10; --n>=0; ) {
-
- switch (zgethdr(Rxhdr, 1)) {
- case ZCHALLENGE: /* Echo receiver's challenge numbr */
- stohdr(Rxpos);
- zshhdr(ZACK, Txhdr);
- continue;
- case ZCOMMAND: /* They didn't see out ZRQINIT */
- stohdr(0L);
- zshhdr(ZRQINIT, Txhdr);
- continue;
- case ZRINIT:
- Rxflags = 0377 & Rxhdr[ZF0];
- Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
-
- Rxbuflen = (0337 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
- vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
- siggi = 0;
- #ifndef READCHECK
- #ifdef USG
- mode(2); /* Set cbreak, XON/XOFF, etc. */
- #else
- /* Use 1024 byte frames if no sample/interrupt */
- if (Rxbuflen < 32 || Rxbuflen > 1024) {
- Rxbuflen = 1024;
- vfile("Rxbuflen=%d", Rxbuflen);
- }
- #endif
- #endif
- /* Override to force shorter frame length */
- if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
- Rxbuflen = Tframlen;
- if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
- Rxbuflen = Tframlen;
- vfile("Rxbuflen=%d", Rxbuflen);
-
- /*
- * If input is not a regular file, force ACK's each 1024
- * (A smarter strategey could be used here ...)
- */
- if ((Rxbuflen == 0) || (Rxbuflen > 1024))
- Rxbuflen = 1024;
- vfile("Rxbuflen=%d", Rxbuflen);
-
- return (sendzsinit());
- case ZCAN:
- case TIMEOUT:
- return ERROR;
- case ZRQINIT:
- if (Rxhdr[ZF0] == ZCOMMAND)
- continue;
- default:
- zshhdr(ZNAK, Txhdr);
- continue;
- }
- }
- return ERROR;
- }
-
- /* Send send-init information */
- sendzsinit()
- {
- register int c;
- register int errors;
-
- if (Myattn[0] == '\0')
- return OK;
-
- errors = 0;
- for (;;) {
- stohdr(0L);
- zsbhdr(ZSINIT, Txhdr);
- zsdata(Myattn, 1+strlen(Myattn), ZCRCW);
- c = zgethdr(Rxhdr, 1);
- switch (c) {
- case ZCAN:
- return ERROR;
- case ZACK:
- return OK;
- default:
- if (++errors > 9)
- return ERROR;
- continue;
- }
- }
- }
-
- /* Send file name and related info */
- zsendfile(buf, blen)
- char *buf;
- int blen;
- {
- register int c;
-
- for (;;) {
- Txhdr[ZF0] = Lzconv; /* file conversion request */
- Txhdr[ZF1] = Lzmanag; /* file management request */
- Txhdr[ZF2] = Lztrans; /* file transport request */
- Txhdr[ZF3] = 0;
- zsbhdr(ZFILE, Txhdr);
- zsdata(buf, blen, ZCRCW);
- again:
- c = zgethdr(Rxhdr, 1);
- switch (c) {
- case ZRINIT:
- goto again;
- case ZCAN:
- case TIMEOUT:
- case ZABORT:
- case ZFIN:
- return ERROR;
- case ZSKIP:
- fprintf(stderr,"\n\n");
- stfclose(in); in = (-1); return c;
- case ZRPOS:
- if(stfseek(in, Rxpos, 0))
- {
- fprintf(stderr,"\r\nError While Seeking file\n");
- return ERROR;
- }
- Txpos = Rxpos; Lastc = (-1); Dontread = FALSE;
- return zsendfdata();
- case ERROR:
- default:
- continue;
- }
- }
- }
-
- /* Send the data in the file */
- zsendfdata()
- {
- register int c, c1, e;
- register int newcnt;
- register long tcount = 0;
- static int tleft = 6; /* Counter for test mode */
-
- if (Baudrate > 300)
- Blklen = 256;
- if (Baudrate > 2400)
- Blklen = KSIZE;
- if (Rxbuflen && Blklen>Rxbuflen)
- Blklen = Rxbuflen;
- if (blkopt && Blklen > blkopt)
- Blklen = blkopt;
- vfile("Rxbuflen=%d Blklen=%d", Rxbuflen, Blklen);
- somemore:
- if (setjmp(intrjmp)) {
- waitack:
- switch (c1 = getinsync()) {
- default:
- case ZCAN:
- fprintf(stderr,"\r\nReceiver Cancelled Transfer\n\n");
- stfclose(in);
- in = (-1);
- return ERROR;
- case ZSKIP:
- fprintf(stderr,"\r\nReceiver forced SKIP Transfer(1)\n\n");
- stfclose(in);
- in = (-1);
- return c1;
- case ZACK:
- tcount += c;
- lreport(tcount);
- /* fall thru */
- case ZRPOS:
- break;
- case ZRINIT:
- return OK;
- }
- }
-
- siggi = 1;
- newcnt = Rxbuflen;
- stohdr(Txpos);
- zsbhdr(ZDATA, Txhdr);
-
- /*
- * Special testing mode. This should force receiver to Attn,ZRPOS
- * many times. Each time the signal should be caught, causing the
- * file to be started over from the beginning.
- */
- #ifdef TESTATTN
- if (Testattn) {
- if ( --tleft)
- while (tcount < 20000) {
- wr_modem(qbf);
- tcount += strlen(qbf);
- #ifdef READCHECK
- while (Bconstat(1)) {
- switch (sreadline(1)) {
- case CAN:
- case ZPAD:
- goto waitack;
- }
- }
- #endif
- }
- siggi = 0; canit();
- stsleep(3); purgeline(); mode(0);
- #ifdef SDEBUG
- if(logf != (FILE *)NULL)
- fclose(logf);
- #endif
-
- /* printf("\nsz: Tcount = %ld\n", tcount); */
- if (tleft) {
- /* printf("\r\nERROR: Interrupts Not Caught\n"); */
- aexit(1);
- }
- aexit(0);
- }
- #endif
-
- do {
- if (Dontread) {
- c = Lastc;
- } else {
- c = zfilbuf(secbuf, Blklen);
- Lastread = Txpos; Lastc = c;
- }
- #ifdef SDEBUG
- if (Verbose > 10)
- vfile("Dontread=%d c=%d", Dontread, c);
- #endif
-
- Dontread = FALSE;
- if (c < Blklen)
- e = ZCRCE;
- else if (Rxbuflen && (newcnt -= c) <= 0)
- e = ZCRCW;
- else
- e = ZCRCG;
- zsdata(secbuf, c, e);
- Txpos += c;
-
- if (e == ZCRCW)
- goto waitack;
- #ifdef READCHECK
- /*
- * If the reverse channel can be tested for data,
- * this logic may be used to detect error packets
- * sent by the receiver, in place of setjmp/longjmp
- * rdchk(fdes) returns non 0 if a character is available
- */
- flush_modem();
- while (Bconstat(1)) {
- switch (sreadline(1)) {
- case CAN:
- case ZPAD:
- zsdata(secbuf, 0, ZCRCE);
- goto waitack;
- }
- }
- #endif
- } while (c == Blklen);
- tcount += c;
- lreport(tcount);
- siggi = 0;
- lsct = 1;
-
- for (;;) {
- stohdr(Txpos);
- zsbhdr(ZEOF, Txhdr);
- switch (getinsync()) {
- case ZACK:
- continue;
- case ZRPOS:
- goto somemore;
- case ZRINIT:
- return OK;
- case ZSKIP:
- fprintf(stderr,"\r\nReceiver forced SKIP Transfer(2)\n\n");
- stfclose(in);
- in = (-1);
- return c;
- default:
- fprintf(stderr,"\r\nErrors while Send Data\n\n");
- stfclose(in);
- in = (-1);
- return ERROR;
- }
- }
- }
-
- /*
- * Respond to receiver's complaint, get back in sync with receiver
- */
- getinsync()
- {
- register int c;
-
- for (;;) {
- #ifdef TESTATTN
- if (Testattn) {
- wr_modem("\r\n\n\n***** Signal Caught *****\r\n");
- Rxpos = 0; c = ZRPOS;
- } else
- #endif
-
- c = zgethdr(Rxhdr, 0);
- switch (c) {
- case ZCAN:
- case ZABORT:
- case ZFIN:
- case TIMEOUT:
- return ERROR;
- case ZRPOS:
- if (Lastc >= 0 && Lastread == Rxpos) {
- Dontread = TRUE;
- } else {
- /* clearerr(in); */ /* In case file EOF seen */
- if(stfseek(in, Rxpos, 0))
- {
- fprintf(stderr,"\r\nError While Seeking file\n");
- return ERROR;
- }
-
- }
- Txpos = Rxpos;
- return c;
- case ZACK:
- return c;
- case ZRINIT:
- case ZSKIP:
- fprintf(stderr,"\n\n");
- stfclose(in);
- in = (-1);
- return c;
- case ERROR:
- default:
- zsbhdr(ZNAK, Txhdr);
- continue;
- }
- }
- }
- /* Say "bibi" to the receiver, try to do it cleanly */
- saybibi()
- {
- for (;;) {
- stohdr(0L);
- zsbhdr(ZFIN, Txhdr);
- switch (zgethdr(Rxhdr, 0)) {
- case ZFIN:
- sendline('O'); sendline('O'); flush_modem();
- case ZCAN:
- case TIMEOUT:
- return;
- }
- }
- }
-
- /* Send command and related info */
- zsendcmd(buf, blen)
- char *buf;
- {
- register int c, errors;
- long cmdnum;
-
- /* cmdnum = getpid(); */
- cmdnum = 1; /* A random # */
- errors = 0;
- for (;;) {
- stohdr(cmdnum);
- Txhdr[ZF0] = Cmdack1;
- zsbhdr(ZCOMMAND, Txhdr);
- zsdata(buf, blen, ZCRCW);
- listen:
- Rxtimeout = 100; /* Ten second wait for resp. */
- c = zgethdr(Rxhdr, 1);
-
- switch (c) {
- case ZRINIT:
- continue;
- case ERROR:
- case TIMEOUT:
- if (++errors > Cmdtries)
- return ERROR;
- continue;
- case ZCAN:
- case ZABORT:
- case ZFIN:
- case ZSKIP:
- case ZRPOS:
- return ERROR;
- default:
- if (++errors > 10)
- return ERROR;
- continue;
- case ZCOMPL:
- Exitcode = Rxpos;
- saybibi();
- return OK;
- case ZRQINIT:
- vfile("******** RZ *******");
- /* stsystem("rz"); */
- vfile("******** SZ *******");
- goto listen;
- }
- }
- }
-
- wr_modem(s)
- register char *s;
- {
- while(*s != '\0')
- Bconout(1, *s++);
- }
-
- /* OLD FASHIONED - but works */
- flush_modem()
- {
- while(Bcostat(1) == 0);
- }
-
- /* Super Duper, but it does'nt work */
- /*
- flush_modem()
- {
- IOREC *piorec;
-
- while(Bcostat(1) == 0); */
-
- /* Get pointer to Rs232 output record */
- /* piorec = (IOREC *)Iorec(0) + sizeof(IOREC); */
-
- /* Wait till head and tail pointers are the same */
- /* while(piorec->ibufhd != piorec->ibuftl) */
- /* loop */ /* ;
- } */
-
- /*
- * If called as sb use YMODEM protocol
- */
- schkinvok(s)
- char *s;
- {
- if (s[0]=='s' && s[1]=='b') {
- Nozmodem = TRUE; Blklen=KSIZE;
- }
- }
-
- /** EOF **/
-